import pygame
from utilities import color
import random
from utilities import enum
from utilities import listutils
import threading

class MapTile:
  TileType = enum.Enum(['black', 'grass', 'dirt', 'sand', 'water'])
  
  def __init__(self, tileType, width, height):
    self.surface = pygame.Surface((width, height))
    self.tileType = tileType
    if self.tileType == MapTile.TileType.black:
      self.surface.fill(color.black)
    else:
      pixels = listutils.list2d(color.black, height, width) #initialize all pixels to black
      
      #initial random loop
      for row in range(height):
        for col in range(width):
          pixels[row][col] = self.randomColor()
          
      #avg surrounding pixels
      for row in range(height):
        for col in range(width):
          r = pixels[row][col].r
          g = pixels[row][col].g
          b = pixels[row][col].b
          count = 1
          if row > 1:
            r = r + pixels[row-1][col].r
            g = g + pixels[row-1][col].g
            b = b + pixels[row-1][col].b
            count = count + 1
          if row < width-1:
            r = r + pixels[row+1][col].r
            g = g + pixels[row+1][col].g
            b = b + pixels[row+1][col].b
            count = count + 1
          if col > 1:
            r = r + pixels[row][col-1].r
            g = g + pixels[row][col-1].g
            b = b + pixels[row][col-1].b
            count = count + 1
          if col < height-1:
            r = r + pixels[row][col+1].r
            g = g + pixels[row][col+1].g
            b = b + pixels[row][col+1].b
            count = count + 1
          pixels[row][col] = pygame.color.Color(r/count, g/count, b/count)
            
      #copy pixels to surface
      self.surface.lock()
      for row in range(height):
        for col in range(width):
          self.surface.set_at((col, row), pixels[row][col])
      self.surface.unlock()
      
  def randomColor(self):
    ret = color.black
    if self.tileType == MapTile.TileType.grass:
      ret = pygame.color.Color(0, random.randint(100, 200), 0)
    elif self.tileType == MapTile.TileType.dirt:
      r = random.randint(100, 150)
      ret = pygame.color.Color(r, r-50,0)
    elif self.tileType == MapTile.TileType.sand:
      g = random.randint(200, 255)
      r = random.randint(g, 255)
      ret = pygame.color.Color(r, g, g-50)
    elif self.tileType == MapTile.TileType.water:
      ret = pygame.color.Color(0, 0, random.randint(100, 200))
    return ret
    
  def draw(self, surface, x, y):
    surface.blit(self.surface, (x, y))
  
  def __str__(self):
    return self.tileType
    
def generateRandomMap(map, tileWidth, tileHeight):
  for row in range(len(map)):
    for col in range(len(map[row])):
      map[row][col] = MapTile(random.choice(MapTile.TileType), tileWidth, tileHeight)

class MapManager:
  def __init__(self, surface, rows, columns, filename=None):
    self.screen = surface
    self.columns = columns
    self.rows = rows
    self.tileWidth = 48
    self.tileHeight = 48
    self.map = listutils.list2d(MapTile(MapTile.TileType.black, self.tileWidth, self.tileHeight), self.rows, self.columns)#initialize self.map[rows][columns] to black
    self.mapGeneratorThread = threading.Thread(target=generateRandomMap, args=(self.map, self.tileWidth, self.tileHeight))
    if filename == None:
      self.randomize()

  def randomize(self):
    self.mapGeneratorThread.start()

  def __str__(self):
    return 'a ' + str(len(self.map)) + 'x' + str(len(self.map[0])) + ' Map'
    
  def draw(self):
    if self.mapGeneratorThread.ident == None or not self.mapGeneratorThread.isAlive():
      cols = self.columns
      rows = self.rows
      for row in range(rows):
        for col in range(cols):
          self.map[row][col].draw(self.screen, col*self.tileWidth, row*self.tileHeight)
    else:
      font = pygame.font.Font(pygame.font.get_default_font(), 20)
      text = font.render('Creating map...', True, color.white)
      self.screen.blit(text, text.get_rect(centerx=self.screen.get_width()/2))
      